import time
from urllib import parse
from typing import Optional
import requests
import hashlib


class Map:

    def __init__(self, ak='xXmHMCueinhyp4VmlCHpeegEKkfcq8tV', sk='wS1TZ0AV3NuAG5FZOAy2GYCQTTbskNiE') -> None:
        self.__ak = ak
        self.__sk = sk
        self.__apiSource = "http://api.map.baidu.com"
        self.__coordTranseUrl = "/geoconv/v1/?"

    def __makeUrl(self, url: str) -> str:
        """
        描述：生成加密后的URL地址
        参数：@url->接口地址[str]
        返回值：加密后可以请求的URL地址[str]
        """
        encodedStr = parse.quote(url, safe="/:=&?#+!$,;'@()*[]")
        rawStr = encodedStr + self.__sk
        sn = (hashlib.md5(parse.quote_plus(rawStr).encode("utf8")).hexdigest())
        targetUrl = parse.quote(self.__apiSource + url + "&sn=" + sn, safe="/:=&?#+!$,;'@()*[]")
        return targetUrl

    def gpsToBD(self, coords, source=1, target=5) -> Optional[tuple]:
        """
        描述：将GPS的经纬坐标转换成百度地图的
        参数：
            @coords -> GPS经纬度坐标[tuple];
            @source -> 源坐标类型[int](
                1：GPS标准坐标（wgs84）；
                2：搜狗地图坐标；
                3：火星坐标（gcj02），即高德地图、腾讯地图和MapABC等地图使用的坐标；
                4：3中列举的地图坐标对应的墨卡托平面坐标;
                5：百度地图采用的经纬度坐标（bd09ll）；
                6：百度地图采用的墨卡托平面坐标（bd09mc）;
                7：图吧地图坐标；
                8：51地图坐标；
            );
            @target -> 目标坐标类型[int](
                3：火星坐标（gcj02），即高德地图、腾讯地图及MapABC等地图使用的坐标；
                5：百度地图采用的经纬度坐标（bd09ll）；
                6：百度地图采用的墨卡托平面坐标（bd09mc）；
            );
        返回值：转换成功的坐标[tuple](经度，维度),失败返回None
        """
        if coords[0] is None and coords[1] is None:
            return None
        coordStr = f"{coords[0]},{coords[1]}"
        sourceUrl = f"{self.__coordTranseUrl}coords={coordStr}&from={source}&to={target}&ak={self.__ak}"
        # print(sourceUrl)      
        targetUrl = self.__makeUrl(sourceUrl)
        # print(targetUrl)
        res = requests.get(targetUrl)
        # print(res.status_code)
        resDict = res.json()
        if resDict['status'] == 0:
            return resDict['result'][0]['x'], resDict['result'][0]['y']
        else:
            return None


if "__main__" == __name__:
    mapTest = Map()
    lastTime = time.time()
    res = mapTest.gpsToBD((106.629889333, 26.388073433))
    nowTime = time.time()
    print(res)
    print(nowTime - lastTime)
